import {
    AfterViewInit, Component, EventEmitter, Inject, Input, OnChanges, OnInit, Output,
    SimpleChanges,
    ViewChild
} from '@angular/core';
import {Tree, TreeModule} from 'primeng/tree';
import {MenuItem,  TreeNode, Message} from 'primeng/api';
import { TreeDragDropService } from 'primeng/api';
import {DA_SERVICE_TOKEN, ITokenService} from '@delon/auth';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/observable/interval';
import 'rxjs/add/observable/fromEvent';
import 'rxjs/add/operator/pluck';
import 'rxjs/add/observable/from';
import 'rxjs/add/observable/forkJoin';

@Component({
  selector: 'app-tree',
  templateUrl: './tree.html',
  styleUrls: ['./tree.less'],
   providers: [TreeDragDropService]
})

export class TreeDemoComponent implements OnInit, OnChanges, AfterViewInit {

    files: TreeNode[];
  selectedFiles: TreeNode[];
    items: MenuItem[];
    @Input() // 输入属性,接受父组件传入的树数据

    title: string;
    searsh: string; // 搜索框内容

    @Input() // 输入属性,接受父组件传入的树数据
    initDate: any[];

    @Input() // 输入属性,接受父组件传入的树数据
    inputSearch: boolean


    @Input() // 输入属性,接受父组件传入的树数据
    noMenu: boolean
    @Input() // 输入属性,接受父组件传入的右击菜单数据
    itemsData: MenuItem[];

    @Input() // 输入属性,接受父组件传入的树搜索框内容文字
    searchTitle: string;
    @Input() // 输入属性,接受父组件传入的右击菜单数据
    selectionType: any;

    @Input() // 输入属性,接受父组件传入的树搜索框内容文字
    nodrop: boolean;




    @Output()
    dropEvent: EventEmitter<string> = new EventEmitter(); // 定义一个输出属性，当点击按钮的时候 发射出去
    @Output()
    inputValue: EventEmitter<string> = new EventEmitter();

    @Output()
    serchValue: EventEmitter<any> = new EventEmitter();
    @Output()
    MenuSelect: EventEmitter<string> = new EventEmitter(); // 定义一个输出属性，当点击按钮的时候 发射出去
    @Output()
    Select: EventEmitter<string> = new EventEmitter(); // 定义一个输出属性，当点击按钮的时候 发射出去
    @Output()
    develop: EventEmitter<string> = new EventEmitter(); // 定义一个输出属性，当点击按钮的时候 发射出
    @Output()
    clickFunc: EventEmitter<string> = new EventEmitter(); // 定义一个输出属性，刷新方法
    funcBhvList: any; // 后台返回的行为列表

    constructor(
        @Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService
    ) {

    }


    ngOnInit() {
        this.getData(); // 初始化树数据
        this.funcBhvList = this.tokenService.get().funcList;
    }


    ngOnChanges(changes: SimpleChanges): void { // 监听 当父组件发生改变的时候，调用初始化数据方法
        this.getData();
    }

    ngAfterViewInit() {
        this.searchaValue(); // 搜索值
    }


    getData() {

        this.files = this.initDate; // 把父组件传输过来的数据，绑定给files数组，完成页面tree页面渲染
        this.funcList(this.itemsData);

        this.selectedFiles = this.files; // 选中节点属性
    }


    // funcList 代码权限处理
    funcList(event) {
       if(event) { // 存在，才去处理
           let funcList = this.tokenService.get().funcList;
           // event.filter(v => funcList.find(item => item === v.id)
           /*filter 方法对数组中的每个元素都执行一次指定的回调函数，并且创建一个新的数组，该数组元素是所有回调函数执行时返回值为 true 的原数组元素。filter不会对空数组进行检测
             find 方法  方法返回数组中符合测试函数条件的第一个元素,方法为数组中的每个元素都调用一次函数执行。
             首先通过filter方法 去查找传过来的右击菜单数据，因为filter只返回为true的元素，所以我们要插入条件，我们就用find方法，找到行为list中和传入的id相同的 两者结合来用。
             此时返回的只是右击菜单中id存在在行为list中的， 即有权限的，如果不存在，那么返回的false，就不会被filter方法返回回来*/
           if(event.filter(v => funcList.find(item => item === v.id)).length > 0) {
               this.items = event.filter(v => funcList.find(item => item === v.id))
           } else {
               this.items =  [{label: '无操作权限', icon: 'fa fa-close'}]
           }

       }
    }

    select($event) {
        this.dropEvent.emit($event); // 发生了拖拽，把拖拽事件发射出去，父组件进行处理
    }


    // 搜索框内传递
    searchaValue() {
        const change = document.getElementById( 'searchaVal');
        const change$ = Observable.fromEvent(change, 'keyup').pluck('target', 'value').debounceTime(600);
        change$.subscribe(val  => {
           this.serchValue.emit(val); // 把搜索值发射出去
        });
    }



    // 展开事件
    Unfold(event) {
        this.develop.emit(event); // 展开了节点树信息
    }

    // 右击菜单事件
    RightSelect(event) {
        this.MenuSelect.emit(event); // 进行了右击，到父组件中去定位右击菜单数据
    }


    // 左击选中事件
    NodeSelect(event) {
        this.Select.emit(event); // 点击了树节点，把节点信息传过去
    }

    treeClick(event) {
        if(event === 'reset') {
            this.clickFunc.emit(event); // 点击了树节点，把节点信息传过去
        } else if(event === 'shrink') {
            // 收缩
            this.initDate.forEach( node => {
                this.expandRecursive(node, false);
            } );
            this.clickFunc.emit(event); // 点击了树节点，把节点信息传过去
        } else if(event === 'expand') {
            // 展开
            this.clickFunc.emit(event); // 点击了树节点，把节点信息传过去
        }
    }

    // 展开/收缩所有树节点的方法
    private expandRecursive(node:TreeNode, isExpand:boolean){
        node.expanded = isExpand;
        if(node.children){
            node.children.forEach( childNode => {
                this.expandRecursive(childNode, isExpand);
            } );
        }
    }
}



